package thread;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: wx
 * Date: 2023-12-16
 * Time: 17:27
 */

/**
 * 总结
 * 在其他编程语言中,加锁解锁都是单独的方式                      横向对比其他语言,java这里的加锁操作风格是 独树一帆 的
 * c++                                                   java                                    java使用代码块设定的
 * std::locker locker;                                   Object locker = new Object               好处: 像 c++ 这种写法可能会忘记调用unclok
 * locker.lock() //加锁                                    synchronized(locker) {                      (unclok 没有执行到)
 * locker.unlock() //解锁                                     }
 *        如果确实要分开 加锁 解锁,就被迫要写作
 *            try{
 *              lock()
 *                 ......
 *
 *            } finally {  finally 无论如何都会执行(最后的后盾)
 *              unlock()   finally 和 final 不是一个东西
 *             }           throw 和 throws 也不是一个东西
 *
 * */
class Test {
    public int count = 0;

    public void add() {
        synchronized(this){
            count++;
        }
    }

   /*
   synchronized public static void func() {  //如果 synchronized 是加到 static 方法上,就等价于给 类对象加锁

    }
    public static void func() {
        synchronized(Test.class){

        }
    }
    */



   /*
   public void add() {
        synchronized(this){  //在这里加锁,等价于直接在 add 方法上直接加锁 synchronized
            count++;         //修饰普通方法,相当于给this加锁
        }
    synchronized public void add() {
            count++;
        }
    */

    /*public void add() {
        count++;
        对他进行修改,加锁,展示在下方
    }*/

    /*
    public void add() {
        synchronized (Test.class) {  //类对象 在 java进程中,一个类的类对象只有一个
            count++;                       //在下述的main2中,第一个线程和第二个线程拿到的类对象都是一个类对象
        }                                  //所以锁竞争是依旧存在的,依旧可以保证线程安全
     */

    /*
    public void add() {
        synchronized(this){
            count++;
        }
    }// 这种写法是否会存在线程安全问题??
     // 指向同一个对象
     // 是线程安全的
     */
  /*
    public void add2() {
        count++;
    }*/
    }


public class ThreadDemo19 {
    //针对加锁对象的一些混淆的理解

    public static void main2(String[] args) throws InterruptedException {


        Test t = new Test();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                t.add();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                t.add();
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("count = " + t.count);
    }

    public static void main1(String[] args) throws InterruptedException {


        Test t = new Test();

        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                t.add();
            }
        });

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 50000; i++) {
                t.add();
            }
        });

        t1.start();
        t2.start();

        t1.join();
        t2.join();

        System.out.println("count = " + t.count);
    }
}
